#ifndef __DEF__
#define __DEF__

#define STATIC static
#define INLINE inline
#define CONST const
#define VOLATILE volatile
#define REG register
#define EXTERN extern
#define EXTERN_C extern "C"

typedef void VOID;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long long QWORD;
typedef long double TWORD;
typedef long LONG;
typedef unsigned long ULONG;
typedef long long LONGLONG;
typedef unsigned long long ULONGLONG;

#ifdef __amd64
typedef unsigned long DWORD;
typedef unsigned long long DWORD_PTR;
#else
typedef unsigned long DWORD;
typedef DWORD DWORD_PTR;
#endif

typedef int BOOL;
typedef unsigned char BOOLEAN;

#define TRUE 1
#define FALSE 0

typedef VOID *PVOID;
typedef BYTE *PBYTE;
typedef WORD *PWORD;
typedef DWORD *PDWORD;
typedef QWORD *PQWORD;
typedef TWORD *PTWORD;
typedef LONG *PLONG;
typedef ULONG *PULONG;
typedef LONGLONG *PLONGLONG;
typedef ULONGLONG *PULONGLONG;

typedef VOID *LPVOID;
typedef BYTE *LPBYTE;
typedef WORD *LPWORD;
typedef DWORD *LPDWORD;
typedef QWORD *LPQWORD;
typedef TWORD *LPTWORD;
typedef LONG *LPLONG;
typedef ULONG *LPULONG;
typedef LONGLONG *LPLONGLONG;
typedef ULONGLONG *LPULONGLONG;

typedef CONST LPVOID *LPCVOID;
typedef CONST LPBYTE *LPCBYTE;

typedef union LARGE_INTEGER {
    DWORD dwLow;
    LONG lHigh;
} *PLARGE_INTEGER, *LPLARGE_INTEGER;

typedef char CHAR;
typedef short WCHAR;

#ifdef UNICODE
typedef WCHAR TCHAR;
#else
typedef CHAR TCHAR;
#endif

typedef CHAR *PCHAR;
typedef WCHAR *PWCHAR;
typedef TCHAR *PTCHAR;

typedef CHAR *LPSTR;
typedef CONST CHAR *LPCSTR;
typedef WCHAR *LPWSTR;
typedef CONST WCHAR *LPCWSTR;
typedef TCHAR *LPTSTR;
typedef CONST TCHAR *LPCTSTR;

typedef unsigned short CHAR16;
typedef unsigned int CHAR32;

typedef LPVOID HANDLE;

typedef HANDLE *PHANDLE;

typedef short SHORT;
typedef int INT;
typedef unsigned short USHORT;
typedef unsigned int UINT;

typedef SHORT *PSHORT;
typedef INT *PINT;
typedef USHORT *PUSHORT;
typedef UINT *PUINT;

typedef float FLOAT32;
typedef double FLOAT64;
typedef long double FLOAT80;

typedef signed char int8_t;
typedef short int16_t;
typedef int int32_t;
typedef long long int64_t;

typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;

typedef float float32_t;
typedef double float64_t;
typedef long double float80_t;

typedef int STATUS;

#define STATUS_NOERR 0
#define STATUS_INVAL 1
#define STATUS_NOMEM 2
#define STATUS_EMPTY 3

#define NULL (0)
#define EOF (-1)
#define FAR

#define __xchg(var1, var2) __asm__("xchg %0,%1":"+r"(var1):"m"(var2))

#define __inbyte(port, var)                                              \
  __asm__("in %%dx,%%al" : "=a"(var) : "d"(port))
#define __inword(port, var)                                              \
  __asm__("in %%dx,%%ax" : "=a"(var) : "d"(port))
#define __indword(port, var)                                             \
  __asm__("in %%dx,%%eax" : "=a"(var) : "d"(port))

#define __outbyte(port, var)                                             \
  __asm__("out %%al,%%dx" ::"a"(var), "d"(port))
#define __outword(port, var)                                             \
  __asm__("out %%ax,%%dx" ::"a"(var), "d"(port))
#define __outdword(port, var)                                            \
  __asm__("out %%eax,%%dx" ::"a"(var), "d"(port))

#define __cli() __asm__("cli")
#define __sti() __asm__("sti")

#define __cld() __asm__("cld")
#define __std() __asm__("std")

#define __clc() __asm__("clc")
#define __stc() __asm__("stc")
#define __cmc() __asm__("cmc")

#define __hlt() __asm__("hlt")

#define __lgdt(ptr) __asm__("lgdt (%0)" ::"r"(ptr))
#define __lidt(ptr) __asm__("lidt (%0)" ::"r"(ptr))
#define __lldt(val) __asm__("lldt %0" ::"r"(val))
#define __ltr(val) __asm__("ltr %0" ::"r"(val))

#define __sgdt(ptr) __asm__("sgdt (%0)" ::"r"(ptr))
#define __sidt(ptr) __asm__("sidt (%0)" ::"r"(ptr))
#define __sldt(val) __asm__("sldt %0" ::"=r"(val))
#define __str(val) __asm__("str %0" ::"=r"(val))

#define __lfence __asm__("lfence")
#define __sfence __asm__("sfence")
#define __mfence __asm__("mfence")

#define __set_cr0(var) __asm__("mov %%eax,%%cr0" ::"a"(var))
#define __set_cr1(var) __asm__("mov %%eax,%%cr1" ::"a"(var))
#define __set_cr2(var) __asm__("mov %%eax,%%cr2" ::"a"(var))
#define __set_cr3(var) __asm__("mov %%eax,%%cr3" ::"a"(var))
#define __set_cr4(var) __asm__("mov %%eax,%%cr4" ::"a"(var))

#define __get_cr0(var) __asm__("mov %%cr0,%%eax" : "=a"(var))
#define __get_cr1(var) __asm__("mov %%cr1,%%eax" : "=a"(var))
#define __get_cr2(var) __asm__("mov %%cr2,%%eax" : "=a"(var))
#define __get_cr3(var) __asm__("mov %%cr3,%%eax" : "=a"(var))
#define __get_cr4(var) __asm__("mov %%cr4,%%eax" : "=a"(var))

typedef char *va_list;
#define va_start(ap, v) (ap = (char *)&v)
#define va_end(ap) (ap = NULL)
#define va_arg(ap, t) *((t *)(ap += 4))

#define TOTAL_MEMORY_BYTES (*(DWORD *)(DWORD_PTR)0xc0000500)

#define __SYSCALL0(no) __asm__("int $0x80" ::"a"(no))
#define __SYSCALL1(no, a) __asm__("int $0x80" ::"a"(no), "b"(a))
#define __SYSCALL2(no, a, b) __asm__("int $0x80" ::"a"(no), "b"(a), "c"(b))
#define __SYSCALL3(no, a, b, c)                                                \
  __asm__("int $0x80" ::"a"(no), "b"(a), "c"(b), "d"(c))

#define __SYSCALL0R(no, ret) __asm__("int $0x80" : "=a"(ret) : "a"(no))
#define __SYSCALL1R(no, a, ret)                                                \
  __asm__("int $0x80" : "=a"(ret) : "a"(no), "b"(a))
#define __SYSCALL2R(no, a, b, ret)                                             \
  __asm__("int $0x80" : "=a"(ret) : "a"(no), "b"(a), "c"(b))
#define __SYSCALL3R(no, a, b, c, ret)                                          \
  __asm__("int $0x80" : "=a"(ret) : "a"(no), "b"(a), "c"(b), "d"(c))

#define SYSCALL_INTR 0x80
#define SYSCALL_CNT 0x100
#define IDT_DESC_CNT 0x81
#define INTR_ENTRY_CNT 0x80

typedef struct {
    ULONG   Data1;
    USHORT  Data2;
    USHORT  Data3;
    BYTE    Data4[8];
} GUID, UUID, IID, CLSID;

#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
        EXTERN_C const GUID DECLSPEC_SELECTANY name \
                = { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } }

VOID Panic(LPCSTR lpPanicMsg);

#endif